#ifndef _UTILS_H_
#define _UTILS_H_

#if _WIN32
#pragma once
#endif

#include "entity.h"

#define GET_OTHER_FROM_PARAM(arr, index, type) *(\
    reinterpret_cast<type*>(arr[index].vpValue))

#define GET_BOOL_FROM_PARAM(arr, index) GET_OTHER_FROM_PARAM(arr, index, bool)
#define GET_USHORT_FROM_PARAM(arr, index) GET_OTHER_FROM_PARAM(arr, index, \
                                                             unsigned short)
#define GET_SSHORT_FROM_PARAM(arr, index) GET_OTHER_FROM_PARAM(arr, index, \
                                                             signed short)
#define GET_ULONG_FROM_PARAM(arr, index) GET_OTHER_FROM_PARAM(arr, index,\
                                                             unsigned long)
#define GET_SLONG_FROM_PARAM(arr, index) GET_OTHER_FROM_PARAM(arr, index,\
                                                             signed long)
#define GET_FLOAT_FROM_PARAM(arr, index) GET_OTHER_FROM_PARAM(arr, index,\
                                                             float)
#define GET_DOUBLE_FROM_PARAM(arr, index) GET_OTHER_FROM_PARAM(arr, index,\
                                                             double)
#define GET_UCHAR_FROM_PARAM(arr, index) GET_OTHER_FROM_PARAM(arr, index,\
                                                             unsigned char)
#define GET_SCHAR_FROM_PARAM(arr, index) GET_OTHER_FROM_PARAM(arr, index,\
                                                             signed char)
#define GET_ENTITY_ID_FROM_PARAM(arr, index) GET_OTHER_FROM_PARAM(arr, index,\
                                                                  ENTITY_ID);

// Don't dereference to get the value of a pointer
#define GET_POINTER_FROM_PARAM(arr, index, type) \
    reinterpret_cast<type*>(arr[index].vpValue)

// To obtain 26 characters from DELAY_PARAMS[1] char*.
// data[512];
// GET_STRING_FROM_PARAM(params, 1, data, 25);
#define GET_STRING_FROM_PARAM(arr, index, data, length) \
    strncpy(data, reinterpret_cast<char*>(arr[index].vpValue), length);

namespace utils {

    typedef enum typeDefinitions
    {
        TYPE_BOOL = 1,
        TYPE_USHORT,
        TYPE_SSHORT,
        TYPE_ULONG,
        TYPE_SLONG,
        TYPE_FLOAT,
        TYPE_DOUBLE,
        TYPE_UCHAR,
        TYPE_SCHAR,
        TYPE_STRING,
        TYPE_ENTITY_ID,
        TYPE_OTHER,
        TYPE_POINTER,
    } TYPE_VALUE;

    typedef struct
    {
        void *vpValue;
        TYPE_VALUE nType;
        int nDereferenceSize; // Used for n sized strings
    } PARAM;
};

#endif 